package cn.yitun.chat.yitunchatbasesdk.server.im.dispatcher.impl;

import cn.yitun.chat.yitunactiondispatch.ActionDispatcher;
import cn.yitun.chat.yitunactiondispatch.common.ActionMethod;
import cn.yitun.chat.yitunactiondispatch.common.ApplyInfo;
import cn.yitun.chat.yitunactiondispatch.extend.ActionInterceptor;
import cn.yitun.chat.yitunactiondispatch.extend.ActionRequest;
import cn.yitun.chat.yitunactiondispatch.extend.ActionResponse;
import cn.yitun.chat.yitunactiondispatch.extend.ArgumentBox;
import cn.yitun.chat.yituncommonlibutil.lib.YitunJsonUtil;
import cn.yitun.chat.yituncommonmessage.Head;
import cn.yitun.chat.yituncommonmessage.Info;
import cn.yitun.chat.yituncommonmessage.client.ClientHead;
import cn.yitun.chat.yituncommonmessage.impl.HeadImpl;
import cn.yitun.chat.yituncommonmessage.result.ResultMessage;
import cn.yitun.chat.yituncommonmessage.server.Result;
import cn.yitun.chat.yituncommonmessage.server.ServerHead;
import cn.yitun.chat.yitungeneral.annotation.validate.Validate;
import cn.yitun.chat.yitungeneral.annotation.validate.Validates;
import cn.yitun.chat.yitunjsonvalidator.ValidatorError;
import cn.yitun.chat.yitunjsonvalidator.ValidatorResult;
import cn.yitun.chat.yitunjsonvalidator.ValidatorService;
import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;

import java.util.List;

/**
 * Date 2019-01-12 12:34:09<br>
 * Description
 * @author yitun
 * @since 1.1
 */

public class HandlerActionInterceptor implements ActionInterceptor {

	private ValidatorService validatorService;
	private ActionDispatcher actionDispatcher;


	public HandlerActionInterceptor(ActionDispatcher actionDispatcher) {
		super();
		this.actionDispatcher = actionDispatcher;
	}

	public ValidatorService getValidatorService() {
		return validatorService;
	}

	public void setValidatorService(ValidatorService validatorService) {
		this.validatorService = validatorService;
	}

	@Override
	public ApplyInfo previous(ActionRequest request, ActionResponse response, ArgumentBox argumentBox) {
		boolean approve = true;
		Object requestData = request.getData();
		Object value = null;
		String message = (requestData instanceof String) ? requestData.toString() : "";
		if (YitunJsonUtil.mayBeJSON(message)) {
			JsonObject jsonObject = new JsonParser().parse(message).getAsJsonObject();

			boolean hasHead = jsonObject.has("head");
			boolean hasBody = jsonObject.has("body");

			if (hasHead && hasBody) {
				JsonObject headJsonObject = jsonObject.getAsJsonObject("head");
				JsonObject bodyJsonObject = jsonObject.getAsJsonObject("body");

				ClientHead head = new Gson().fromJson(headJsonObject, ClientHead.class);
				ServerHead resultHead = new Gson().fromJson(headJsonObject, ServerHead.class);

				String path = argumentBox.get("requestPath");
				if (null == path) {
					String classCode = head.getAction();
					String methodCode = head.getMethod();
					path = getPath(classCode, methodCode);
				}

				argumentBox.put(Head.class, head);
				argumentBox.put(ClientHead.class, head);
				argumentBox.put(HeadImpl.class, head);
				argumentBox.put(ServerHead.class, resultHead);


//				使用validate.json类似文件校验请求
				if (null != validatorService) {
					Info info = new Info();
					ActionMethod method = request.getActionMethod();
					if (null != method) {
						Validates vs = method.getMethod().getAnnotation(Validates.class);
						if (null != vs) {
							validate(bodyJsonObject, vs, info);
						} else {
							Validate v = method.getMethod().getAnnotation(Validate.class);
							if (null != v) {
								validate(bodyJsonObject, v, info);
							} else {
								validate(bodyJsonObject, path, null, info);
							}
						}
					} else {
						validate(bodyJsonObject, path, null, info);
					}
					if (!info.isSuccess()) {
						ResultMessage m = new ResultMessage();
						m.setInfo(info);
						m.setHead(head);

						value = (m);
						approve = false;
					}
				}



			} else {
				Result r = new Result();
				r.setCode(HeadImpl.code_fail);
				r.setMessage("参数错误！");

				ServerHead head = new ServerHead();
				head.setAction("");
				head.setMethod("");
				head.setResult(r);

				ResultMessage m = new ResultMessage();
				m.setHead(head);
				value = (m);

				approve = false;
			}
		} else {
			Result r = new Result();
			r.setCode(HeadImpl.code_fail);
			r.setMessage("请求协议异常！");

			ServerHead head = new ServerHead();
			head.setAction("");
			head.setMethod("");
			head.setResult(r);
			head.setTimestamp(System.currentTimeMillis());

			ResultMessage m = new ResultMessage();
			m.setHead(head);

			value = (m);
			approve = false;
		}

		ApplyInfo applyInfo = new ApplyInfo();
		applyInfo.setApprove(approve);
		applyInfo.setValue(value);
		return applyInfo;
	}

	public String getPath(String classCode, String methodCode) {
		return actionDispatcher.getActionRegistry().getPath(classCode, methodCode);
	}

	private void validate(JsonObject jsonObject, Validates vs, Info info) {
		if (null != vs) {
			Validate[] values = vs.value();
			if (null != values && values.length > 0) {
				for (Validate v : values) {
					validate(jsonObject, v, info);
				}
			}
		}
	}

	private void validate(JsonObject jsonObject, Validate v, Info info) {
		if (null != v && null != v.value() && !v.value().isEmpty()) {
			String name = v.value();
			String p = v.property();
			if (null != p && !p.isEmpty()) {
				if (jsonObject.has(p) && jsonObject.get(p) instanceof JsonElement) {
					JsonObject jo = jsonObject.getAsJsonObject(p);
					validate(jo, name, p, info);
				} else if (v.required()) {
					info.addError(ValidatorError.is_null, p + "不能为空！");
				}
			} else {
				validate(jsonObject, name, null, info);
			}
		}
	}

	private void validate(JsonObject jsonObject, String name, String property, Info info) {
		if (validatorService.hasValidate(name)) {
			List<ValidatorResult> list = validatorService.validate(jsonObject, name);
			if (!list.isEmpty()) {
				for (ValidatorResult vr : list) {
					StringBuilder sb = new StringBuilder();
					if (null != property && !property.isEmpty()) {
						sb.append(property);
						sb.append(".");
					}
					sb.append(vr.getPropertyPath());
					sb.append(vr.getMessage());
					info.addError(vr.getErrorCode(), sb.toString());
				}
			}
		}
	}

//	private ResultMessage getResult() {
//		HeadImpl head = new HeadImpl();
//		head.setAction("");
//		head.setMethod("");
//		head.setTimestamp(System.currentTimeMillis());
//
//		ResultMessage m = new ResultMessage();
//		m.setHead(head);
//		return m;
//	}
}
